//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#ifndef _ListE_h_
#define _ListE_h_
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#include "Node.h"
#include "Node.cpp"
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
template <class T>
class TListE {

  private :

    long              length;

    TNode <T>*        first;
    TNode <T>*        final;

    TNode <T>*        previous;
    TNode <T>*        current;
    TNode <T>*        next;

  protected:

    typedef void      (*TFunctionAction)(TNode <T>*, void*);

    typedef bool      (*TFunctionConditionalB)(TNode <T>*, void*);
    typedef bool      (*TFunctionConditionalBParameters)(TNode <T>*, void*, void*);

    typedef int       (*TFunctionConditionalI)(TNode <T>*, void*);
    typedef double    (*TFunctionConditionalD)(TNode <T>*, void*);

    void              MixList(TFunctionConditionalB, void*, TListE <T>*);
    void              MixListX(TFunctionConditionalB, void*, TListE <T>*, TListE <T>*, TListE <T>*);

    void              MixList(TFunctionConditionalBParameters, void*, void*, TListE <T>*);
    void              MixListX(TFunctionConditionalBParameters, void*, void*, TListE <T>*, TListE <T>*, TListE <T>*);

    TNode <T>*        PosNode(long);
    void              SetCurrent(TNode <T>*);

  public :

    TListE();
    TListE(T*);
    TListE(TListE <T>*);
    TListE(TListE <T>&);

    ~TListE();

    void          Add(T*);
    void          AddIni(T*);
    void          AddNode(TNode <T>*);
    void          AddNodeIni(TNode <T>*);

    void          Add(T);
    void          AddIni(T);
    void          AddNode(TNode <T>);
    void          AddNodeIni(TNode <T>);

    void          Delete(long);
    void          Delete(T*);
    void          DeleteCurrent();

    void          Insert(T*, long);
    void          InsertBeforeCurrent(T*);
    void          InsertAfterCurrent(T*);

    void          InsertNode(TNode <T>*, long);
    void          InsertNodeBeforeCurrent(TNode <T>*);
    void          InsertNodeAfterCurrent(TNode <T>*);

    T*            Transfer(long);
    T*            TransferCurrent();

    TNode <T>*    TransferNode(long);
    TNode <T>*    TransferCurrentNode();

    void          TransferAll();

    void          Destroy(long);
    void          DestroyCurrent();

    bool          Update(T*, long);

    long          Length();

    void          SetPosition(long);
    void          SetInitial();
    bool          SetNext();

    T*            Get(long);
    T*            GetPrevious();
    T*            GetCurrent();
    T*            GetNext();
    T*            GetFirst();
    T*            GetFinal();

    TNode <T>*    GetNode(long);
    TNode <T>*    GetPreviousNode();
    TNode <T>*    GetCurrentNode();
    TNode <T>*    GetNextNode();
    TNode <T>*    GetFirstNode();
    TNode <T>*    GetFinalNode();

    static void   ExchangeElement(T*, T*);
    static void   ExchangeNode(TNode <T>*, TNode <T>*);

    void          ExchangeBlocks(long, long, long, long);
    void          ExchangeBlocks(long, long, long);

    void          ForEach(TFunctionAction, void*);
    void          ForEachFrom(TNode <T>*, TFunctionAction, void*);

    T*            FirstOcurrence(TFunctionConditionalB, void*);
    T*            FirstOcurrence(TFunctionConditionalBParameters, void*, void*);
    T*            FirstOcurrenceFrom(TNode <T>*, TFunctionConditionalB, void*);

    long          FirstOcurrencePosition(TFunctionConditionalB, void*);
    
    void          AllOcurrence(TFunctionConditionalB, TListE <T>*, void*);
    void          AllOcurrence(TFunctionConditionalBParameters, TListE <T>*, void*, void*);
    void          AllOcurrenceFrom(TNode <T>*, TFunctionConditionalB, TListE <T>*, void*);

    void          ConsecutiveSubList(TFunctionConditionalB, TListE <T>*, void*);
    void          ConsecutiveSubList(TFunctionConditionalBParameters, TListE <T>*, void*, void*);
    void          CleanConsecutiveSubList();

    void          AllOcurrenceCond(TFunctionConditionalI, TListE <T>*, void*);
    void          AllOcurrenceCondFrom(TNode <T>*, TFunctionConditionalI, TListE <T>*, void*);

    void          RepresentativeOcurrencesAfterOrdered(TFunctionConditionalBParameters, TListE <T>*, void*);
    void          RepresentativeOcurrences(TFunctionConditionalBParameters, TListE <T>*, void*);

    long          NumberOcurrence(TFunctionConditionalB, void*);
    long          NumberOcurrence(TFunctionConditionalBParameters, void*, void*);
    long          NumberOcurrenceFrom(TNode <T>*, TFunctionConditionalB, void*);
    long          NumberOcurrenceFrom(TNode <T>*, TFunctionConditionalBParameters, void*, void*);

    void          OrderList(TFunctionConditionalB, void*);

    void          OrderListCentered(TFunctionConditionalD, void*);

    void          OrderListByList(TFunctionConditionalB, TListE <T>*);
    void          OrderListByList(TFunctionConditionalBParameters, TListE <T>*, void*);

    void          QuickSortList(TFunctionConditionalB, void*);
    void          QuickSortList(TFunctionConditionalBParameters, void*, void*);

    void          CompactListAfterOrdered(TFunctionConditionalB, void*);

    bool          Empty();
    bool          Clear();

    TListE <T>    operator=(TListE <T>&);

};
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#endif
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
